/**
 * Copyright (c) 2015-2020, wss 王山山
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wss.conversion.auto;

import java.util.List;

import com.jfinal.aop.Interceptor;
import com.jfinal.config.Interceptors;
import com.jfinal.log.JdkLoggerFactory;
import com.jfinal.log.Logger;
import com.wss.conversion.Constants;
import com.wss.conversion.annotations.AutoInterceptor;
import com.wss.conversion.validate.ConversionValidate;
import com.wss.conversion.validate.impl.InterceptorConversionValidate;
import com.wss.utils.ReflectionUtil;
import com.wss.utils.scan.ScanUtil;

/**
 * 自动配置拦截器
 * @author wss
 *
 */
public class AutoConfigInterceptor implements AutoConfig {
	private static final Logger LOG = new JdkLoggerFactory().getLogger(AutoConfigInterceptor.class);
	
	private final ConversionValidate CONVERSION_VALIDATE = InterceptorConversionValidate.newInstance();
	
	private Interceptors interceptors;
	
	public AutoConfigInterceptor(Interceptors interceptors) {
		this.interceptors = interceptors;
	}
	
	@Override
	public void config() {
		String interceptorPackage = applicationConfig.getMain().getInterceptorPackage();		
		List<String> interceptorNames = ScanUtil.scanClassesUnderPackageRecursive(interceptorPackage);
		interceptorNames.stream()
			.filter(CONVERSION_VALIDATE::namedValidate)
			.map(ReflectionUtil::loadClass)
			.filter(CONVERSION_VALIDATE::classValidate)
			.filter(e -> ReflectionUtil.hasAnnotation(e, Constants.InterceptorConstants.AUTOINTERCEPTOR_CLASS))
			.sorted((e1, e2) -> compare(e1, e2))
			.forEach(this::addInterceptor);
	}
	
	private void addInterceptor(Class<?> clazz) {
		interceptors.add((Interceptor) ReflectionUtil.newInstance(clazz));
		if (devMode) {
			LOG.info("Interceptor Register >>> [" + clazz.getName() + "]");
		}
	}
	
	private int compare(Class<?> clazz1, Class<?> clazz2) {
		AutoInterceptor at1 = ReflectionUtil.getAnnotationByType(clazz1, Constants.InterceptorConstants.AUTOINTERCEPTOR_CLASS).get();
		AutoInterceptor at2 = ReflectionUtil.getAnnotationByType(clazz2, Constants.InterceptorConstants.AUTOINTERCEPTOR_CLASS).get();
		return at1.value() - at2.value();
	}
}
